﻿using System.Collections;
using System.Dynamic;

namespace CommandLib
{
    /// <summary>
    /// dynamic动态封装类，属性字段可以动态定义与ExpandoObject相当
    /// </summary>
    public class DyObject : DynamicObject, IEnumerable
    {

        //保存对象动态定义的属性值  
        private IDictionary<string, object> values;
        /// <summary>
        /// 自义定动态类，须要用dynamic接收和设置动态的属性
        /// </summary>
        public DyObject()
        {
            values = new Dictionary<string, object>();

        }
        /// <summary>
        /// 获取本类数据
        /// </summary>
        public object GetValue { get { return values; } }
        /// <summary>  
        /// 获取属性值  
        /// </summary>  
        /// <param name="propertyName"></param>  
        /// <returns></returns>  
        public object GetPropertyValue(string propertyName)
        {
            if (values.ContainsKey(propertyName))
            {
                return values[propertyName];
            }
            return null;
        }
        /// <summary>  
        /// 设置属性值  
        /// </summary>  
        /// <param name="propertyName"></param>  
        /// <param name="value"></param>  
        public void SetPropertyValue(string propertyName, object value)
        {
            if (values.ContainsKey(propertyName))
            {
                values[propertyName] = value;
            }
            else
            {
                values.Add(propertyName, value);
            }
        }
        /// <summary>  
        /// 实现动态对象属性成员访问的方法，得到返回指定属性的值  
        /// </summary>  
        /// <param name="binder"></param>  
        /// <param name="result"></param>  
        /// <returns></returns>  
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = GetPropertyValue(binder.Name);
            return result == null ? false : true;
        }
        /// <summary>  
        /// 实现动态对象属性值设置的方法。  
        /// </summary>  
        /// <param name="binder"></param>  
        /// <param name="value"></param>  
        /// <returns></returns>  
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            SetPropertyValue(binder.Name, value);
            return true;
        }
        /// <summary>  
        /// 动态对象动态方法调用时执行的实际代码  
        /// </summary>  
        /// <param name="binder"></param>  
        /// <param name="args"></param>  
        /// <param name="result"></param>  
        /// <returns></returns>  
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var theDelegateObj = GetPropertyValue(binder.Name) as DO;
            if (theDelegateObj == null || theDelegateObj.CallMethod == null)
            {
                if (binder.Name == "set" && binder.CallInfo.ArgumentCount == 2)
                {
                    string name = args[0] as string;
                    if (name == null)
                    {
                        result = null;
                        return false;
                    }
                    object value = args[1];
                    values.Add(name, value);
                    result = value;
                    return true;

                }
                return base.TryInvokeMember(binder, args, out result);
            }
            result = theDelegateObj.CallMethod(this, args);
            return true;
        }

        public IEnumerator GetEnumerator()
        {
            return values.GetEnumerator();
        }
    }


    public class DO
    {
        public delegate object MyDelegate(dynamic Sender, params object[] PMs);
        public delegate void MyAction(dynamic Sender, params object[] param);
        private MyDelegate _delegate;     
        /// <summary>
        /// 获取委托方法
        /// </summary>
        public MyDelegate CallMethod
        {
            get { return _delegate; }
        }
        private DO(MyDelegate D)
        {
            _delegate = D;
        }     
        /// <summary>  
        /// 构造委托对象.动态调用属性方法  
        /// </summary>  
        /// <param name="D">委托方法</param>  
        /// <returns></returns>  
        public static DO Function(MyDelegate D)
        {
            return new DO(D);
        }
     
    }  

}
